package com.itheima.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.aop.Log;
import com.itheima.common.JwtUtils;
import com.itheima.common.PageBean;
import com.itheima.dto.EmpDto;
import com.itheima.dto.LoginDto;
import com.itheima.dto.QueryEmpDto;
import com.itheima.mapper.EmpExprMapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
import com.itheima.pojo.EmpExpr;
import com.itheima.service.EmpService;
import com.itheima.vo.EmpJobVo;
import com.itheima.vo.EmpVo;
import com.itheima.vo.ItemVo;
import com.itheima.vo.LoginVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class EmpServiceImpl implements EmpService {

    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private EmpExprMapper empExprMapper;

    /**
     * 分页条件查询
     *
     * @param dto
     * @return
     */
    @Override
    @Log
    public PageBean pageQuery(QueryEmpDto dto) {
        //dto.setPage((dto.getPage() - 1) * dto.getPageSize());
        //1. 查询集合数据rows
        //List<Emp> list = empMapper.list(dto);
        //2. 查询总条数total
        //Integer total = empMapper.countTotal(dto);
        //3. 返回PageBean对象
        //PageBean pageBean = new PageBean(total, list);
        //return pageBean;

        //使用PageHepler分页
        PageHelper.startPage(dto.getPage(), dto.getPageSize());
        //紧接着后面的select就会被分页
        Page<EmpVo> page = empMapper.list(dto);

        PageBean pageBean = new PageBean(page.getTotal(), page.getResult());
        return pageBean;
    }

    /**
     * 添加员工，以及工作经历
     *
     * @param dto
     */
    @Override
    @Transactional //表示方法需要使用事务管理
    public void addEmp(EmpDto dto) {
        //1. 添加员工信息（操作emp表，1条数据）
        Emp emp = new Emp();
        //将dto中的属性拷贝到emp对象中（属性一致）
        BeanUtils.copyProperties(dto, emp);
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setPassword("123456");//默认密码
        //添加员工数据到数据库
        empMapper.insert(emp); //主键自增返回

        //2. 添加工作经历（操作emp_expr表，N条数据）
        List<EmpExpr> exprList = dto.getExprList();
        exprList.forEach(empExpr -> {
            //设置每一个EmpExpr的empId属性
            empExpr.setEmpId(emp.getId());
            //添加每一条工作经历
            empExprMapper.insert(empExpr);
        });
    }

    /**
     * 根据id查询员工信息（以及员工工作经历）
     *
     * @param id
     * @return
     */
    @Override
    public EmpVo getById(Integer id) {
        //1. 创建EmpVo对象
        EmpVo empVo = new EmpVo();
        //2. 根据id查询Emp员工基础信息  Emp
        Emp emp = empMapper.getById(id);
        //3. 根据id查询工作经历List<EmpExpr>
        List<EmpExpr> exprList = empExprMapper.getByEmpId(id);
        //4. 将Emp、List封装到EmpVo对象中
        BeanUtils.copyProperties(emp, empVo);
        empVo.setExprList(exprList);

        return empVo;
    }

    /**
     * 修改员工信息
     *
     * @param dto
     */
    @Override
    @Transactional //表示方法需要使用事务管理
    public void updateById(EmpDto dto) {
        Emp emp = new Emp();
        BeanUtils.copyProperties(dto, emp);
        //1. 先修改员工的基本信息
        empMapper.updateById(emp);

        //2. 再根据员工id删除工作经历
        empExprMapper.deleteByEmpId(emp.getId());

        //3. 最后添加员工的工作经历
        List<EmpExpr> exprList = dto.getExprList();
        exprList.forEach(empExpr -> {
            //将设置EmpExpr对象的empId属性
            empExpr.setEmpId(emp.getId()); //一定不能少
            empExprMapper.insert(empExpr);
        });
    }

    /**
     * 删除员工
     *
     * @param ids
     */
    @Override
    public void delete(List<Integer> ids) {
        ids.forEach(id -> {
            //1. 删除员工基本信息
            empMapper.deleteById(id);
            //2. 删除员工工作经历信息
            empExprMapper.deleteByEmpId(id);
        });

    }

    /**
     * 查询所有
     *
     * @return
     */

    @Override
    public List<Emp> list() {
        return empMapper.findAll();
    }

    /**
     * 统计员工性别
     *
     * @return
     */
    @Override
    public List<ItemVo> getEmpGenderData() {
        return empMapper.getEmpGenderData();
    }

    /**
     * 统计员工职位
     *
     * @return
     */
    @Override
    public EmpJobVo getEmpJobData() {
        List<ItemVo> list = empMapper.getEmpJobData();

        //使用hutools工具包来实现
        List<String> jobs = CollUtil.getFieldValues(list, "name", String.class);
        List<Integer> counts = CollUtil.getFieldValues(list, "value", Integer.class);

        //使用stream流实现
        //遍历 List<ItemVo>， 将每个ItemVo的职位名称获取出来，形成一个新的List<String>
        //List<String> jobs = list.stream().map(vo -> vo.getName()).collect(Collectors.toList());
        //遍历 List<ItemVo>， 将每个ItemVo的职位数量获取出来，形成一个新的List<Integer>
        //List<Integer> counts = list.stream().map(vo -> vo.getValue()).collect(Collectors.toList());

        return EmpJobVo.builder().jobList(jobs).dataList(counts).build();
    }

    /**
     * 员工登录
     *
     * @param dto
     * @return
     */
    @Override
    public LoginVo login(LoginDto dto) {
        //先根据用户名查询
        Emp emp = empMapper.getByUsername(dto.getUsername());
        if (emp == null) {
            //说明用户名不存在
            throw new RuntimeException("用户名不存在");
        }

        //再判断用户密码（字符串比较，建议大家使用工具类）
        boolean flag = StringUtils.equals(emp.getPassword(), dto.getPassword());
        if (!flag) {
            //说明密码不正确
            throw new RuntimeException("密码错误");
        }


        //用户名密码正确，说明登录成功
        //生成jwt令牌（用户身份）
        Map<String, Object> map = new HashMap<>();
        map.put("id", emp.getId());
        String jwt = JwtUtils.generateJwt(map); //hutools

        return LoginVo.builder()
                .id(emp.getId())
                .name(emp.getName())
                .username(emp.getUsername())
                .token(jwt)
                .build();
    }
}
